#include "playeritems.h"
#include "gametable.h"
#include "player.h"
#include "playerskillobject.h"
#include "gamedialogmanager.h"
#include "gamedialog.h"
#include "tileboarditems.h"
#include <QFontDatabase>
#include <QStyleOptionGraphicsItem>
#include <QDebug>
#include "windowskin.h"

/*

  TAOFEILDBG CLASS

*/
TaoFieldBg::TaoFieldBg(GameBoardOrganizer *parent,int w,int h)
    :GameBoardItem(parent),_width(w),_height(h)
{
    this->setOpacity(0.5);
    this->setAcceptHoverEvents(true);

}

QRectF TaoFieldBg::boundingRect() const
{
    return QRectF(-_width/2,-_height/2,_width,_height);
}

void TaoFieldBg::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->fillRect(boundingRect(),QBrush(Qt::gray));
    //painter->drawText(boundingRect(), Qt::AlignCenter, "Tao Field");
}

/*

  TaoSlot CLASS

*/
TaoSlot::TaoSlot(GameBoardOrganizer *parent)
    :GameBoardItem(parent)
{
    this->setOpacity(0.5);
    //this->setAcceptHoverEvents(true);
}

QRectF TaoSlot::boundingRect() const
{
    return QRectF(-TSLOT_WIDTH/2,-TSLOT_HEIGHT/2,TSLOT_WIDTH,TSLOT_HEIGHT);
}

void TaoSlot::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->fillRect(boundingRect(),QBrush(Qt::gray));
    //painter->drawText(boundingRect(), Qt::AlignCenter);
}

/*

  TaoItem CLASS

*/

TaoItem::TaoItem(GameBoardItem *parent, gs::GSColor c)
    :QGraphicsObject(parent),_taoColor(c)
{
    setTaoPix(_taoColor);
}

void TaoItem::setTaoPix(gs::GSColor c)
{
    switch(c)
    {
        case RED:
            _taoPix = QPixmap(":/Tao/images/shu.png");
            break;
        case YELLOW:
            _taoPix = QPixmap(":/Tao/images/god.png");
            break;
        case BLUE:
            _taoPix = QPixmap(":/Tao/images/wei.png");
            break;
        case GREEN:
            _taoPix = QPixmap(":/Tao/images/wu.png");
            break;
        case BLACK:
            _taoPix = QPixmap(":/Tao/images/qun.png");
            break;
        case WHITE:
            break;
        default:
            break;
    }
}

QRectF TaoItem::boundingRect() const
{
    return QRectF(-TAO_WIDTH/2,-TAO_HEIGHT/2,TAO_WIDTH,TAO_HEIGHT);
}

void TaoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //painter->fillRect(boundingRect(),QBrush(Qt::red));
    painter->drawPixmap(-TAO_WIDTH/2,-_taoPix.height()/2,_taoPix.width(),_taoPix.height(),_taoPix);
}

/*

  PlayerHead CLASS

*/

PlayerHead::PlayerHead(GameBoardOrganizer *parent, QPixmap p)
    :GameBoardItem(parent), _headPix(p)
{
}

QRectF PlayerHead::boundingRect() const
{
    return QRectF(-WIDTH/2, -HEIGHT/2, WIDTH, HEIGHT);
}
void PlayerHead::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPainterPath path;
    path.addRoundRect(QRectF(-WIDTH/2-5, -HEIGHT/2-5, WIDTH+10, HEIGHT+10), 15);
    painter->fillPath(path, Qt::white);
    painter->drawPixmap(-_headPix.width()/2, -_headPix.height()/2,_headPix);
}

/*

  PlayerQi CLASS

*/

PlayerQi::PlayerQi(GameBoardOrganizer *parent,int qiNum)
    :GameBoardItem(parent),_qiNum(qiNum)
{
    _qiPix = QPixmap(":/playerHead/images/qi_icon.png");
    QFontDatabase::addApplicationFont( tr(":/font/font/CHILLER.TTF") );
    _font = QFont( "Chiller" );
    _font.setPixelSize( 15 );
    _font.setBold( true );
}

QRectF PlayerQi::boundingRect() const
{
    return QRectF(-QI_AREA_WIDTH/2,-QI_AREA_HEIGHT/2,QI_AREA_WIDTH,QI_AREA_HEIGHT);
}

void PlayerQi::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->fillRect(boundingRect(),QBrush(Qt::gray));
    painter->setFont( _font );
    painter->drawPixmap(-QI_AREA_WIDTH/2,-_qiPix.height()/2,_qiPix.width(),_qiPix.height(),_qiPix);
    painter->drawText((_qiPix.width()-QI_AREA_WIDTH/2+GAP),-TEXT_HEIGHT/2,TEXT_WIDTH,TEXT_HEIGHT, Qt::AlignRight,"X "+QString::number(_qiNum));
}

/*

  PlayerYin CLASS

*/

PlayerYin::PlayerYin(GameBoardOrganizer *parent)
    :GameBoardItem(parent)
{
    _yinPix = QPixmap(":/common/images/skill_yinyang.png");
   this->setAcceptHoverEvents(true);
}

QRectF PlayerYin::boundingRect() const
{
    return QRectF(-YIN_WIDTH/2,-YIN_HEIGHT/2,YIN_WIDTH,YIN_HEIGHT);
}

void PlayerYin::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{

    painter->drawPixmap(-YIN_WIDTH/2,-YIN_HEIGHT/2,YIN_WIDTH,YIN_HEIGHT,_yinPix);
}

/*

  PlayerBudd CLASS

*/

PlayerBudd::PlayerBudd(GameBoardOrganizer *parent)
    :GameBoardItem(parent)
{
    //_buddPix = QPixmap("")
    this->setAcceptHoverEvents(true);
}

QRectF PlayerBudd::boundingRect() const
{
    return QRectF(-BUDD_WIDTH/2,-BUDD_HEIGHT/2,BUDD_WIDTH,BUDD_HEIGHT);
}

void PlayerBudd::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //painter->drawPixmap();
    painter->fillRect(boundingRect(),QBrush(Qt::gray));
    painter->drawText(boundingRect(), Qt::AlignCenter, "Buddha Area");
}

/*

  PlayerSkill CLASS

*/

PlayerSkill::PlayerSkill(GameBoardOrganizer *parent)
    :GameBoardItem(parent)
{
    setSkillInfo();
    this->setAcceptHoverEvents(true);
    connect(currentBoard,SIGNAL(skill_sealed()),this,SLOT(sealSkill()));
    connect(currentBoard,SIGNAL(skill_released()),this,SLOT(unsealSkill()));

}

void PlayerSkill::setSkillInfo()
{
    BottomTable* bt = dynamic_cast<BottomTable*>(this->getParentBoard()->getParentBoard());
    currentPlayer = bt->getGameTable()->getCurrentPlayer();
    currentBoard = currentPlayer->getGhostBoard();
    currentSkill = currentPlayer->getPlayerSkill();
    _skillPix = currentSkill->getSkillIcon();
    isUseable = currentSkill->getUseable();

}

QRectF PlayerSkill::boundingRect() const
{
    return QRectF(-SKILL_WIDTH/2,-SKILL_HEIGHT/2,SKILL_WIDTH,SKILL_HEIGHT);
}

void PlayerSkill::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //painter->fillRect(boundingRect(),QBrush(Qt::gray));
    //painter->drawText(boundingRect(), Qt::AlignCenter, "Skill Area");
    painter->drawPixmap(-SKILL_WIDTH/2,-SKILL_HEIGHT/2,SKILL_WIDTH,SKILL_HEIGHT,_skillPix);
}

void PlayerSkill::mousePressEvent(QGraphicsSceneMouseEvent *event){

    if(isUseable){
        currentSkill->setSkillEffect(this->getDialogManager());
        this->setOpacity(1.0);
        update();
    }
}

void PlayerSkill::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    this->setOpacity(0.5);
    update();
}

void PlayerSkill::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    this->setOpacity(1.0);
    update();
}
void PlayerSkill::sealSkill()
{
    this->setEnabled(false);
    currentPlayer->setSkillSealed(true);
    update();
}
void PlayerSkill::unsealSkill()
{
    this->setEnabled(true);
    currentPlayer->setSkillSealed(false);
    update();
}

/*

  ActionButton CLASS

*/

ActionButton::ActionButton(GameBoardOrganizer *parent,QString title)
    :GameBoardItem(parent),_title(title)
{
    //_actPix = QPixmap("");
    QFontDatabase::addApplicationFont( tr(":/font/font/CHILLER.TTF") );
    _font = QFont( "Chiller" );
    _font.setPixelSize( 10 );
    _font.setBold( true );
    this->setAcceptHoverEvents(true);
    this->setOpacity(0.5);
}

QRectF ActionButton::boundingRect() const
{
    return QRectF(-BUTTON_WIDTH/2,-BUTTON_HEIGHT/2,BUTTON_WIDTH,BUTTON_HEIGHT);
}

void ActionButton::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //painter->drawPixmap();
    painter->setFont( _font );


    painter->fillRect(-BUTTON_WIDTH/2,-BUTTON_HEIGHT/2,BUTTON_WIDTH,BUTTON_HEIGHT,QBrush(Qt::gray));
    painter->drawText(boundingRect(), Qt::AlignCenter, _title);
}

void ActionButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    this->setScale(0.98);
    update();
}

void ActionButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    this->setScale(1.0);
    update();
}

/*

  MOVE BUTTON CLASS

*/
MoveButton::MoveButton(GameBoardOrganizer *parent, QString title)
    :ActionButton(parent,title)
{

}

void MoveButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    GameTileRequestDialog* diaRef = this->getDialogManager()->getTileRequestDialog();

    GameTable* currentTable = this->getParentBoard()->getGameTable();
    CenterTable* cTable = currentTable->getCenterTable();

    connect(cTable,SIGNAL(clicked(VillageTile*)),diaRef,SLOT(receiveClickOnTile(VillageTile*)));
    VillageTile* tile = this->getDialogManager()->askTileDialog();
    disconnect(cTable, SIGNAL(clicked(VillageTile*)), diaRef, SLOT(receiveClickOnTile(VillageTile*)));

    QPoint* clickedPos = tile->getPos();
    Player* currentPlayer = currentTable->getCurrentPlayer();
    QPoint* moveDir = currentPlayer->getMoveDistance(clickedPos);
    //A player can not move more than 2 steps
    if(qAbs(moveDir->x())<2 && qAbs(moveDir->y())<2){
        currentPlayer->setPlayerPos(clickedPos);
        return;
    }
    //Player with skill 1 can move more than 2 steps
    if(currentPlayer->getPlayerSkill()->getSkillId()==1 && !currentPlayer->isSkillSealed()){
        currentPlayer->setPlayerPos(clickedPos);
        return;
    }
}


/*

  SHOP BUTTON CLASS

*/
ShopButton::ShopButton(GameBoardOrganizer *parent, QString title)
    :ActionButton(parent,title)
{
    currentPlayer = this->getParentBoard()->getGameTable()->getCurrentPlayer();
    if(currentPlayer->isActionUsed())
        this->setEnabled(false);
}
void ShopButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    this->getDialogManager()->askTestShop();
    currentPlayer->setActionUsed(true);
}

/*

  FIGHT BUTTON CLASS

*/
FightButton::FightButton(GameBoardOrganizer *parent, QString title)
    :ActionButton(parent,title)
{
    currentPlayer = this->getParentBoard()->getGameTable()->getCurrentPlayer();
    if(currentPlayer->isActionUsed())
        this->setEnabled(false);
}
void FightButton::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    GhostSlot* temp = this->getParentBoard()->getGameTable()->getGhostBoards().at(0)->getSlots().at(1);
    this->getDialogManager()->askBattleDialog(temp);
    currentPlayer->setActionUsed(true);
    update();
}

/*

  FrontTaoField CLASS

*/
FrontTaoField::FrontTaoField(GameTable* t,GameBoardOrganizer* b,Player* p)
    :GameBoardOrganizer(t,b),_pl(p)
{
    this->setAcceptHoverEvents(true);
    _bg = new TaoFieldBg(this,FRONT_WIDTH,FRONT_HEIGHT);
    setFrontRow();
    connect(_pl,SIGNAL(taoChanged()),this,SLOT(updateTao()));
}

void FrontTaoField::setFrontRow()
{
    int gap = 4;
    int slotw = TaoSlot::TSLOT_WIDTH;
    QList<gs::GSColor> colorList;
    colorList << YELLOW << GREEN << RED
              << BLUE << BLACK;
    QList<int> taoNumList;
    taoNumList << _pl->getResistY() << _pl->getResistG()
               << _pl->getResistR() << _pl->getResistBlue()
               << _pl->getResistBlack();
    for(int i=0;i<5;i++){
        TaoSlot* frontSlot = new TaoSlot(this);
        TaoItem* currentTao = new TaoItem(frontSlot,colorList.at(i));
        currentTao->setVisible(false);
        frontTaos.append(currentTao);
        frontSlot->setOpacity(1);
        frontSlot->moveBy(-FRONT_WIDTH/2+slotw*(i*2+1)/2+gap*(i+1),0);
    }
}

void FrontTaoField::updateTao()
{
    //add taoitem at the front row

    QList<int> taoNumList;
    taoNumList << _pl->getResistY() << _pl->getResistG()
               << _pl->getResistR() << _pl->getResistBlue()
               << _pl->getResistBlack();
    int frontNum = frontTaos.size();
    for(int i=0;i<frontNum;i++){
        if(taoNumList.at(i)>0){
            frontTaos.at(i)->setVisible(true);
        }
        else{
            frontTaos.at(i)->setVisible(false);
        }
    }
    update();

}

/*

  HiddenTaoField CLASS

*/
HiddenTaoField::HiddenTaoField(GameTable *t, GameBoardOrganizer *b,Player* p)
    :GameBoardOrganizer(t,b),_pl(p)
{
    this->setVisible(false);
    _bg = new TaoFieldBg(this,HIDDEN_WIDTH,HIDDEN_HEIGHT);
    setHiddenRow();
    connect(_pl,SIGNAL(taoChanged()),this,SLOT(updateTao()));
}

void HiddenTaoField::setHiddenRow()
{
    int gap = 4;
    int slotw = TaoSlot::TSLOT_WIDTH;
    int sloth = TaoSlot::TSLOT_HEIGHT;
    QList<gs::GSColor> colorList;
    colorList << YELLOW << GREEN << RED
              << BLUE << BLACK;

    for(int i=0;i<5;i++){

        for(int j=0;j<3;j++){
            TaoSlot* hiddenSlot = new TaoSlot(this);
            hiddenSlot->moveBy(-HIDDEN_WIDTH/2+slotw*(i*2+1)/2+gap*(i+1),
                               -HIDDEN_HEIGHT/2+sloth*(j*2+1)/2+gap*(j+1));
            TaoItem* currentTao = new TaoItem(hiddenSlot,colorList.at(i));
            currentTao->setVisible(false);
            hiddenTaos.append(currentTao);

        }

    }

}

void HiddenTaoField::updateTao()
{
    QList<int> taoNumList;
    taoNumList << _pl->getResistY() << _pl->getResistG()
               << _pl->getResistR() << _pl->getResistBlue()
               << _pl->getResistBlack();
    //add taoitems on the corresponding slots
    for(int i=0;i<5;i++){
        switch(taoNumList.at(i)){
            case 2:
                for(int j=2;j>=0;j--)
                    hiddenTaos.at(i*3+j)->setVisible(false);

                hiddenTaos.at(i*3+2)->setVisible(true);
                break;
            case 3:
                for(int j=2;j>=0;j--)
                    hiddenTaos.at(i*3+j)->setVisible(true);

                hiddenTaos.at(i*3)->setVisible(false);
                break;
            case 4:
                for(int j=2;j>=0;j--)
                    hiddenTaos.at(i*3+j)->setVisible(true);

                break;
            default:
                for(int j=2;j>=0;j--)
                    hiddenTaos.at(i*3+j)->setVisible(false);

        }
    }
    update();

}

/*

  PlayerTaoField CLASS


*/

PlayerTaoField::PlayerTaoField(GameTable* t,GameBoardOrganizer* b, Player* p)
    :GameBoardOrganizer(t,b),_pl(p)
{
    this->setAcceptHoverEvents(true);

    setTaoSlots();

}

void PlayerTaoField::setTaoSlots()
{

    _frontTao = new FrontTaoField(this->getGameTable(),this,_pl);
    _hiddenTao = new HiddenTaoField(this->getGameTable(),this,_pl);
    _hiddenTao->moveBy(0,-FrontTaoField::FRONT_HEIGHT/2-HiddenTaoField::HIDDEN_HEIGHT/2);


}

void PlayerTaoField::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    _hiddenTao->setVisible(true);
}

void PlayerTaoField::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    _hiddenTao->setVisible(false);
}


/*

  PlayerBasic CLASS

*/

PlayerBasic::PlayerBasic(GameTable *t, GameBoardOrganizer *b,Player* p)
    :GameBoardOrganizer(t,b),_pl(p)
{
    setItems();
}

void PlayerBasic::setItems()
{

    _ph = new PlayerHead(this,_pl->getPlayerHead());
    _ph->moveBy(-BASIC_WIDTH/2,-PlayerHead::HEIGHT/2+BottomTable::HEIGHT/2);
    _pq = new PlayerQi(this,_pl->getQi());
    _pq->moveBy(-BASIC_WIDTH/2+10+PlayerHead::WIDTH/2+PlayerQi::QI_AREA_WIDTH/2,0);
    _ps = new PlayerSkill(this);
    _ps->moveBy(-BASIC_WIDTH/2+10+PlayerHead::WIDTH/2+PlayerQi::QI_AREA_WIDTH+PlayerSkill::SKILL_WIDTH/2,0);
    _py = new PlayerYin(this);
    _py->moveBy(-BASIC_WIDTH/2+10+PlayerHead::WIDTH/2+PlayerQi::QI_AREA_WIDTH+PlayerSkill::SKILL_WIDTH
                            +PlayerYin::YIN_WIDTH/2,0);
    _pb = new PlayerBudd(this);
    _pb->moveBy(-BASIC_WIDTH/2+10+PlayerHead::WIDTH/2+PlayerQi::QI_AREA_WIDTH+PlayerSkill::SKILL_WIDTH
                +PlayerYin::YIN_WIDTH+PlayerBudd::BUDD_WIDTH/2,0);
}

/*

  PlayerAction CLASS

*/

PlayerAction::PlayerAction(GameTable *t, GameBoardOrganizer *b,Player* p)
    :GameBoardOrganizer(t,b),_pl(p)
{
    setActionButtons();
}

void PlayerAction::setActionButtons()
{
    _moveAction = new MoveButton(this,"Move");
    _moveAction->moveBy((-ActionButton::BUTTON_WIDTH-GAP)*2,0);
    _shopAction = new ShopButton(this,"Shop");
    _shopAction->moveBy((-ActionButton::BUTTON_WIDTH-GAP)*1,0);
    _fightAction = new FightButton(this,"Fight");
    _finishAction = new ActionButton(this,"Finish");
    _finishAction->moveBy((ActionButton::BUTTON_WIDTH+GAP)*1,0);
    _playerInfo = new ActionButton(this,"Info");
    _playerInfo->moveBy((ActionButton::BUTTON_WIDTH+GAP)*2,0);
}

